import { WeaSearchGroup,WeaSelect,WeaTools ,WeaErrorPage ,WeaFormItem ,WeaBrowser,WeaDialog,WeaRightMenu} from 'ecCom';
import {inject, observer} from "mobx-react/index";
import { Button , Modal , Row , Col , Icon} from 'antd';
import {WeaLocaleProvider} from 'ecCom';
import cloneDeep from 'lodash/cloneDeep';
import isArray from 'lodash/isArray';
import isEmpty from 'lodash/isEmpty';
import sortBy from 'lodash/sortBy';
import * as mobx from 'mobx';
import {convertSpecialChar} from '../../util/signUtil';
import {getBranchLastGroup} from './workflowFreeUtils';
const { toJS } = mobx;
const getLabel = WeaLocaleProvider.getLabel;

import WorkflowFreeNode from './WorkflowFreeNode';
import WorkflowFreeNodeGroup from './WorkflowFreeNodeGroup';

import { getFreeObjById , isExistThisElement , getCurrentElementPoint , getFirstParentHaveNext 
         , checkCurrentNodeIsPassed , getElementBranchLevel} from './workflowFreeUtils';

@observer
class WorkflowFree extends React.Component{
    constructor(props) {
        super(props);
        this.state = {}
    }
    componentDidMount = () => {
        const { templateid = -1 , modelSetModalShow = false } = this.props;
        if(templateid != -1){
            modelSetModalShow && this.initalFreeDatas(this.props);
        }else{
            this.initalFreeDatas(this.props);
        }
    }
    initalFreeDatas(props = {}){
        const { workflowNewDesignStore , currentRequestId = '' , requestid = '' , workflowid = '' , nodeid ='', cellMaxHeight=0,
            createNodeInfo = {},isFree='',isAllowNodeFreeFlow='1',templateid = -1,isFromHtmlPage=false,isFlowModel,
            f_weaver_belongto_userid,f_weaver_belongto_usertype,authSignatureStr,authStr,wfTestStr,belongTest = '0', wf_chart_ready_windowClose,showForecastNode} = props;
        const { initalFreeWfDatas , setOrginWfNodesInfo } = workflowNewDesignStore;
        /**
        isAllowNodeFreeFlow: 0 || 1, 自由节点节点
        isFree : 0 || 1 , 自由流程
        两者是互斥的  一方为1 另一个则为0 
         */
        const postParams = {
            isFree,
            nodeid,
            workflowid,
            requestid,
            templateid,
            isAllowNodeFreeFlow,
            isFromHtmlPage,
            f_weaver_belongto_userid,
            f_weaver_belongto_usertype,
            wfTestStr,
            authSignatureStr,
            authStr,
            belongTest,
            showForecastNode
        }
        initalFreeWfDatas(postParams,wf_chart_ready_windowClose);
        if(isFlowModel != '1'){
            setOrginWfNodesInfo({createNodeInfo,cellMaxHeight});
        }
    }
    componentWillReceiveProps = (nextProps) => {
        const { templateid = '' , modelSetModalShow = false} = nextProps;
        if(templateid != ''){//来自模板设置
            (!this.props.modelSetModalShow && modelSetModalShow) && this.initalFreeDatas(nextProps);
        }
    }
    
    componentWillUnmount() {
        const { workflowNewDesignStore} = this.props;
        const { clearMobxState } = workflowNewDesignStore;
        clearMobxState();
    }
    
    render(){
        let { workflowNewDesignStore , cellMaxHeight = 0 , createNodeInfo = {} , isReadOnlyModel , isFromHtmlPage=false,isFlowModel} = this.props;
        const { wfFreeDatas , wfFreeDatasPoints , currentFreeWfEditState , isNeedChangeRow , clearCurrentChooseState,allValidNodesPostions,componentNeedRender} = workflowNewDesignStore;

        let maxX = 0 , maxY = 0;
        for( let key in wfFreeDatasPoints){
            let curObj = wfFreeDatasPoints[key];
            for(let subKey in curObj){
                let obj = curObj[subKey];
                maxX = maxX > obj.x ? maxX : obj.x;
                maxY = maxY > obj.y ? maxY : obj.y;
            }
        }
        let svgStyle = {
            width:maxX + 100 + 'px',
            minWidth:'100%',
            height : maxY + 80 + 'px',
            overflow : 'auto'
        }
        let freeSvgStyle = {
            right:isFlowModel=='1' ? '400px' : 0
        }
        isReadOnlyModel = isReadOnlyModel == 'true' ? true : false;

        /** 渲染nodes 和 分支 连接线 */
        let allNodes = [] , allBranchs = [] , svgLinesArr = [] , supLines = [];
        const _wfFreeDatas = mobx.toJS(wfFreeDatas);
        if(_wfFreeDatas && !isEmpty(_wfFreeDatas)){
            for(let key in _wfFreeDatas){
                let arr = _wfFreeDatas[key];
                arr.map((v,i)=>{
                    /**绘制连接线 */
                    if(!isEmpty(v)){
                        let nodePos = allValidNodesPostions[v.freeStartNodeid || key*1];
                        let lineStartPos;
                        isFlowModel == '1' ? lineStartPos = {x:0,y:0} : {x:nodePos.x,y:0};
                        let linesArr = this.renderSvgPath_vertical(v,lineStartPos,true,{},v,`${key}_${i}`);
                        //将svg元素中有颜色变化的放置在最后，才能排在最高层级 避免被遮盖
                        svgLinesArr = svgLinesArr.concat(linesArr.filter(v=>!v.props.upLevel).concat(linesArr.filter(v=>v.props.upLevel)));
                        /************/
                        /**绘制节点 */
                        allNodes = allNodes.concat(this.drawElementNode(v,true,`${key}_${i}`));
                        /**绘制分支 */
                        allBranchs = allBranchs.concat(this.drawGroupsElement(v,true,`${key}_${i}`));
                        /** 绘制自由节点 于 固定流程节点的辅助线 */
                        if(isFlowModel!='1'){
                            supLines = supLines.concat(this.renderSupStartAndEndLine(v,`${key}_${i}`));
                        }
                    }   
                });
            }
        }
        /***********/

        return (
            <div className='wf-design-free-svg-container'>
                <div className='wf-design-free-svg' style = {freeSvgStyle}>
                    <svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" style={svgStyle}>
                        {svgLinesArr}
                    </svg>
                    <div className='wf-design-free-nodeInfo'>
                        {allNodes}
                    </div>
                    <div className='wf-design-free-brachGroups'>
                        {allBranchs}
                    </div>
                    {supLines}
                    {isFlowModel!='1'&&!isReadOnlyModel && this.renderSignHideBtn()}
                </div>
            </div>
        )
    }
    drawGroupsElement(element={},inital=false,posTag=''){
        let { isReadOnlyModel , workflowNewDesignStore} = this.props;
        const { wfFreeDatasPoints , globalNextNodeEditPurview,currentPostParams} = workflowNewDesignStore;
        let groupsElements = [];
        const {nodeid = 0} = currentPostParams;
        const { nodeElement = false , hasNext = false , next = {} , nodeEntity = {} , id='',nodeChartEntity = {}} = element;
        const { addNext = false } = nodeChartEntity;
        isReadOnlyModel = isReadOnlyModel == 'true' ? true : false;
        if(!nodeElement){
            let subElements = element.parallelNodeGroupDatas || [];
            if(subElements.length > 1){
                let branchElementPts = getCurrentElementPoint(element,wfFreeDatasPoints,posTag) || [{},{}];
                let firstElementPts = getCurrentElementPoint(subElements[0],wfFreeDatasPoints,posTag);
                let lastElementPts = getCurrentElementPoint(subElements[subElements.length - 1],wfFreeDatasPoints,posTag);
                if(firstElementPts){
                    isArray(firstElementPts) ? firstElementPts = firstElementPts[0] : '';
                }
                if(lastElementPts){
                    isArray(lastElementPts) ? lastElementPts = lastElementPts[0] : '';
                }
                
                let groupsElementStyle = {
                    left : firstElementPts.x - 58 + 'px',
                    top : (branchElementPts[0] ? branchElementPts[0].y + 10 : -5) + 'px',
                    width : (Math.abs(lastElementPts.x - firstElementPts.x) + 140) + 'px',//两个节点宽度的一半 加上分支信息 预留空间20
                    height :  '180px',
                };
                let needMergeAddBtn = !isReadOnlyModel && addNext;
                if(needMergeAddBtn){
                    groupsElements.push(this.drawGroupsSupButton(branchElementPts[1],element.id,posTag));
                }
                groupsElements.push(
                    <WorkflowFreeNodeGroup ecId={`${this && this.props && this.props.ecId || ''}_WorkflowFreeNodeGroup@8qow9z@${id}`} 
                        groupStyle = {groupsElementStyle} 
                        groupsParams = {element} 
                        isReadOnlyModel = {isReadOnlyModel}
                        isMobile = {this.props.isMobile}
                        workflowNewDesignStore = {workflowNewDesignStore}
                        belongWhereTag = {posTag}
                    />
                );
                subElements.map(v=>{
                    let subNodes = this.drawGroupsElement(v,false,posTag);
                    subNodes.map(c=>{
                        groupsElements.push(c);
                    });
                })
            }
        }
        if(hasNext){
            let subNodes = this.drawGroupsElement(next,false,posTag);
            subNodes.map(v=>{
                groupsElements.push(v);
            });
        }
        return groupsElements;
    }
    drawGroupsSupButton(position={},groupsId='',posTag){//在分支合并处添加一处按钮可进行正常添加操作
        const { workflowNewDesignStore , nodeParams = {} , isMobile = '0'} = this.props;
        const { beSerialNodes} = workflowNewDesignStore;
        const mobileStyle = {
            display:'block',
            fontSize: '18px',
            marginTop: '-1px',
            marginLeft:'-2px',
            lineHeight: '16px',
        };
        return (
            <div className="groups-element-sup-addBtn" title={getLabel(506900,'添加串行节点')}
                style={{
                    left:position.x - 8 + 'px' ,
                    top : position.y - 8 + 'px',
                    border : isMobile == '1' ? 'none' : '1px solid #979797',
                    background : isMobile == '1' ? 'none' : '#FFFFFF'
                }} onClick={()=>beSerialNodes(groupsId,posTag)}>
                <span className="icon-coms-Enlarge" style={isMobile == '1'?mobileStyle:{}}></span>
            </div>
        )
    }
    drawElementNode(element={},inital=false,posTag=''){//posTag = startId_arrayIndex
        let { isFlowModel = '0' , workflowNewDesignStore , isReadOnlyModel} = this.props;
        const { wfFreeDatasPoints } = workflowNewDesignStore;
        const { nodeElement = false , hasNext = false , next = {} , nodeEntity = {} , id = ''} = element;
        let elementNodes = [];
        let currentELtPoint = getCurrentElementPoint(element,wfFreeDatasPoints,posTag);
        isReadOnlyModel = isReadOnlyModel == 'true' ? true : false;
        //nodeType分为处理和审批,查阅 ------审批-1 | 提交-2 | 查阅-4
        if(nodeElement){
            let style = isFlowModel == '1' ? {
                left : currentELtPoint.x - (nodeEntity.nodetype == '1' ? 39 : 
                    nodeEntity.nodetype == '0' ? 45 :
                    nodeEntity.nodetype == '3' ? 20 : 54) + 'px',
                top : currentELtPoint.y  - ((nodeEntity.nodetype == '0' || nodeEntity.nodetype == '3') ? 48 : 35) + 'px'
            } : {
                left : currentELtPoint.x - (nodeEntity.nodetype == '1' ? 39 : 54) + 'px',
                top : currentELtPoint.y  - 35 + 'px'
            };
            elementNodes.push(
                <WorkflowFreeNode ecId={`${this && this.props && this.props.ecId || ''}_WorkflowFreeNode@0fgnvz@${id}`}
                    nodeParams = {element} nodeStyle ={style} 
                    isReadOnlyModel = {isReadOnlyModel}
                    isFlowModel = {this.props.isFlowModel}
                    isMobile = {this.props.isMobile}
                    workflowNewDesignStore = {workflowNewDesignStore}
                    belongWhereTag = {posTag}
                />
            );
        }else{
            let elts = element.parallelNodeGroupDatas;
            let subNodes = [];
            elts && elts.map(v=>{
               let ssubNodes = this.drawElementNode(v,false,posTag);
               ssubNodes.map(c=>{
                   subNodes.push(c);
               })
            });
            subNodes.map(v=>{
                elementNodes.push(v);
            });
        }
        if(hasNext){
            let subNodes = this.drawElementNode(next,false,posTag);
            subNodes.map(v=>{
                elementNodes.push(v);
            });
        }
        return elementNodes;
    }
    renderSupStartAndEndLine(element={},pointIndex=''){//绘制链接自由流程图和原流程图的开始和结束线段
        const { workflowNewDesignStore , cellMaxHeight = 0 , createNodeInfo = {} , isFree} = this.props;
        const {wfFreeDatasPoints , circulationParams,allValidNodesPostions,allValidNodesNodeLinks,
        validWorkFlowDatas,currentSignSetNode , everyFreeNodeOffsetY,circulationOrginNode,forecastNodeIds} = workflowNewDesignStore;
        const { freeStartNodeid = '' , freeEndNodeid = ''} = element;
        const { flowType='1'} = currentSignSetNode;
        const {  currentStartNode} = validWorkFlowDatas;
        let startPosition = allValidNodesPostions[freeStartNodeid];
        let curFreeNodeOffsetY = everyFreeNodeOffsetY[freeStartNodeid] || 0;

        const endElement = getBranchLastGroup(element) || {};
        const {nodeChartEntity = {}} = endElement;
        const {outLineStatus = 0} = nodeChartEntity;
        const {inLineStatus = 0 } = element.nodeChartEntity || {}

        let secondPt = {};
        if(element.nodeElement){
            secondPt = getCurrentElementPoint(element,wfFreeDatasPoints,pointIndex) || {};
        }else{
            secondPt = getCurrentElementPoint(element,wfFreeDatasPoints,pointIndex)[0] || {};
        }
        let supLines = [];
        let bgColor = circulationParams.noPassedLinkColor;
        let supStart , supEnd ;
        if(!isEmpty(mobx.toJS(element))){
            let freeNodeEndArr = [];
            if(freeStartNodeid == freeEndNodeid) {
                const {allOrginNodes = []} = toJS(circulationOrginNode);
                let linkname  = '';
                for (let index = 0; index  < allOrginNodes.length ;index++) {
                    let item = allOrginNodes[index];
                    if(item.nodeId  == freeStartNodeid) {
                        linkname = item.value;
                        break
                    }
                }
                freeNodeEndArr.push({
                    id:'',
                    descnode : freeStartNodeid,
                    linkname : '',
                    linkinfo : linkname,
                    ispass : outLineStatus == 1 ? '1' : '0'
                })
            } else {
                freeNodeEndArr = allValidNodesNodeLinks[freeStartNodeid] || [];
            }
            // *******************
            cloneDeep(toJS(freeNodeEndArr)).map((v,i)=>{
                const linktitle = convertSpecialChar(v.linkinfo);
                let endPosition = cloneDeep(allValidNodesPostions[v.descnode]);
                let ispassed = outLineStatus == 1 && v['ispass'] == '1';

                let endArrowStyle = {
                    position: 'absolute',
                    // borderBottom: `9px solid ${ispassed ? circulationParams.passedLinkColor:'#8c8c8c'}`,
                    borderBottom: `9px solid ${this.getStrockColor(freeEndNodeid, ispassed ? 1 : 0, '#8c8c8c', v.descnode)}`,
                    borderLeft: '4px solid transparent',
                    borderRight: '4px solid transparent',
                    left: '-3.5px',
                    top: '-1px',
                }

                if(freeStartNodeid == v.descnode){
                    endPosition = {...endPosition,x:endPosition.x+5};
                }

                let commonStyle = {
                    width:'1px',
                    position:'absolute',
                };
                if(i == 0){
                    let _left = (isFree != '1' && freeStartNodeid == freeEndNodeid) ? startPosition.x - 5 : startPosition.x;
                    supLines.push(
                        <div className='free-wf-sup-line sup-line-start' 
                            style={{
                                ...commonStyle,
                                left:`${_left}px`,
                                top : -(startPosition.y) + 'px',
                                height:`${(secondPt.x > startPosition.x ? startPosition.y + 10 : startPosition.y + curFreeNodeOffsetY)}px`,
                                //background : inLineStatus == 1 ? circulationParams.passedLinkColor : bgColor
                                background : this.getStrockColor(undefined, inLineStatus, bgColor, v.descnode)
                            }}
                        >
                        </div>
                    );
                    /**辅助  提示 */
                    supLines.push(
                        <div className='free-wf-sup-line sup-line-start' 
                            style={{
                                ...commonStyle,
                                width:'10px',
                                left:`${_left-5}px`,
                                top : -(startPosition.y) + 'px',
                                height:`${(secondPt.x > startPosition.x ? startPosition.y + 10 : startPosition.y) + curFreeNodeOffsetY}px`,
                                background : 'transparent'
                            }}
                        >
                        </div>
                    )
                }
                supLines.push(
                    <div className='free-wf-sup-line sup-line-end' 
                        style={{
                            ...commonStyle,
                            left:`${endPosition.x}px`,
                            height:`${endPosition.y + curFreeNodeOffsetY}px`,
                            top : -(endPosition.y) + 'px',
                            // background : ispassed ? circulationParams.passedLinkColor : bgColor
                            background : this.getStrockColor(freeEndNodeid, ispassed ? 1 : 0, bgColor, v.descnode)
                        }}
                        title={linktitle}
                    >
                    <span style={endArrowStyle}></span>
                    </div>
                );
                /**辅助  提示 */
                supLines.push(
                    <div className='free-wf-sup-line sup-line-end' 
                        style={{
                            ...commonStyle,
                            width:'10px',
                            left:`${endPosition.x-5}px`,
                            height:`${endPosition.y + curFreeNodeOffsetY}px`,
                            top : -(endPosition.y) + 'px',
                            background : 'transparent'
                        }}
                        title={linktitle}
                    >
                    </div>
                );
            })
        }
        return supLines;
    }
    renderSvgPath_vertical(data={},startPos,inital = false,preNode={},element={},ptIndex=''){
        //元素没有next 有父级 链接到父级
        //元素没有next 没有父级 链接到外部流程图
        const {  workflowNewDesignStore , isSingle = false , isFlowModel = '0' , isFree} = this.props;
        const { wfFreeDatasPoints, circulationParams , allValidNodesPostions} = workflowNewDesignStore;
        const { freeStartNodeid = '',freeEndNodeid=''} = data;
        let startPosition = allValidNodesPostions[freeStartNodeid] || {};

        startPos = startPos || startPosition;

        const { nodeEntity = {},nodeElement} = data;
        const { nodeStatus = '0' , nodetype='' , nodename=''} = nodeEntity;

        const {nodeChartEntity = {}} = data;
        const {inLineStatus = 0,outLineStatus = 0} = nodeChartEntity;

        let pathArr = [];
        if(inital){//绘制链接主流程图的连接线
            let secondPt = {};
            if(nodeElement){
                secondPt = getCurrentElementPoint(data,wfFreeDatasPoints,ptIndex) || {};
            }else{
                secondPt = getCurrentElementPoint(data,wfFreeDatasPoints,ptIndex)[0] || {};
            }

            let strokeColor = this.getStrockColor(nodeEntity.id, inLineStatus);
            let pathProps = {
                fill:'none',
                stroke: strokeColor,
                strokeWidth:'1',
                strokeMiterlimit:10
            }
            let _startPos = {
                x: (isFree!='1' && freeStartNodeid == freeEndNodeid) ? startPosition.x - 5  : startPosition.x ,
                y :0
            };

            let supHoverParams = {
                strokeWidth:10,
                stroke : 'transparent',
                fill : 'none'
            }
            if(secondPt.x <= _startPos.x){
                pathArr.push(
                    <path d={`M${secondPt.x-0.5} -0.5 L${secondPt.x-0.5} ${secondPt.y-0.5}`} {...pathProps}>
                        <title>{nodename}</title>
                    </path>
                );
                pathArr.push(
                    <path d={`M${_startPos.x} 0.5 L${secondPt.x} ${0.5}`} {...pathProps}
                            stroke = {this.getStrockColor(nodeEntity.id, inLineStatus, '#666666')}
                            >
                            <title>{nodename}</title>
                    </path>
                );
                /** 悬浮辅助线条 不然1px svg元素不好选中显示title信息*/
                pathArr.push(
                    <path d={`M${secondPt.x-0.5} -0.5 L${secondPt.x-0.5} ${secondPt.y-0.5}`} {...supHoverParams}>
                        <title>{nodename}</title>
                    </path>
                );
                pathArr.push(
                    <path d={`M${_startPos.x} 0.5 L${secondPt.x} ${0.5}`} {...supHoverParams}>
                            <title>{nodename}</title>
                    </path>
                );
                /***************/
            }else if(secondPt.x > _startPos.x){
                pathArr.push(
                    <path d={`M${secondPt.x-0.5} ${9.5} L${secondPt.x-0.5} ${secondPt.y-0.5}`} {...pathProps}>
                        <title>{nodename}</title>
                    </path>
                );
                if(Math.abs(secondPt.x - _startPos.x) >= 2){
                    let adjustValue = 1;
                    pathArr.push(
                        <path d={`M${_startPos.x+adjustValue} ${9.5} L${secondPt.x} ${9.5}`} {...pathProps}
                                stroke = {this.getStrockColor(nodeEntity.id, inLineStatus, '#666666')}
                                >
                                <title>{nodename}</title>
                        </path>
                    );
                }
                /** 悬浮辅助线条 不然1px svg元素不好选中显示title信息*/
                pathArr.push(
                    <path d={`M${secondPt.x-0.5} ${9.5} L${secondPt.x-0.5} ${secondPt.y-0.5}`} {...supHoverParams}>
                        <title>{nodename}</title>
                    </path>
                );
                pathArr.push(
                    <path d={`M${_startPos.x} ${9.5} L${secondPt.x} ${9.5}`} {...supHoverParams}>
                            <title>{nodename}</title>
                    </path>
                );
                /***************/
            }
            if(nodeElement && isFlowModel !='1'){
                pathArr.push(this.renderSvgArrow(secondPt,'fill',inLineStatus == 1,true,nodetype, nodeEntity.id));
            }
            let _path = this.renderSvgPath_vertical(data , secondPt , false , preNode , element,ptIndex);
            _path.map(v=>{
                pathArr.push(v);
            })

        }else{
            if(data.nodeElement){//判断如果这个节点流转过的话，线条颜色变化
                let elementPts = getCurrentElementPoint(data,wfFreeDatasPoints,ptIndex);
                let _path = []; 
                
                let currentElementPts = {
                    x : elementPts.x,
                    y : elementPts.y
                }

                _path = this.renderSvgLine_vertical([startPos,currentElementPts],data,inLineStatus);
                _path.map(v=>{
                    pathArr.push(v); 
                });
                if(data.hasNext){
                    _path = this.renderSvgPath_vertical(data.next , currentElementPts , false , data , element,ptIndex);//x 坐标是否需要加上节点宽度一半
                    _path.map(v=>{
                        pathArr.push(v); 
                    })
                }else{
                    let parent = getFreeObjById(data.parentid,element);
                    if(!data.parentid || !parent){
                        let arr = this.drawLastSvgLine(0,outLineStatus == 1,currentElementPts,nodetype,element,ptIndex,outLineStatus);
                        arr.map(v=>{
                            pathArr.push(v); 
                        });
                    }
                    if(data.parentid != '' && data.parentid != null && parent != null){
                        //获取到第一个拥有next的父级 判断是否流转过
                        let parentPts = getCurrentElementPoint(parent,wfFreeDatasPoints,ptIndex); // is array
                        _path = this.renderSvgLine_vertical([currentElementPts,parentPts[1]],data,outLineStatus);//没有下一节点，存在分支当中
                        _path.map(v=>{
                            pathArr.push(v); 
                        })
                    }
                }
            }else{
                let elementPts = getCurrentElementPoint(data,wfFreeDatasPoints,ptIndex);
                let _path = [];
                //判断数组中元素是否存在流转过的节点
                _path = this.renderSvgLine_vertical([startPos,elementPts[0]],data,inLineStatus);
                _path.map(v=>{
                    pathArr.push(v); 
                });
                let paraArr = data.parallelNodeGroupDatas;
                paraArr.map(v=>{
                    _path =this.renderSvgPath_vertical(v , elementPts[0],false,data,element,ptIndex);
                    _path.map(v=>{
                        pathArr.push(v); 
                    });
                })
                if(data.hasNext){
                    _path =this.renderSvgPath_vertical(data.next , elementPts[1],false,data,element,ptIndex);
                    _path.map(v=>{
                        pathArr.push(v); 
                    });
                }else{
                    let parent = getFreeObjById(data.parentid,element);
                    if(!data.parentid || !parent){
                        const groupStatus = data.groupStatus || '0';
                        let arr = this.drawLastSvgLine(0,outLineStatus == 1,elementPts[1],nodetype,element,ptIndex);
                        arr.map(v=>{
                            pathArr.push(v); 
                        });
                    }
                    //获取到第一个拥有next的父级 判断是否流转过
                    if(data.parentid != null && parent != null){
                        let parentPts = getCurrentElementPoint(parent,wfFreeDatasPoints,ptIndex); // is array

                        _path = this.renderSvgLine_vertical([elementPts[1],parentPts[1]],parent,outLineStatus);
                        _path.map(v=>{
                            pathArr.push(v); 
                        })
                    }
                }
            }
        }
        return pathArr;
    }
    renderSvgLine_vertical(points=[],currNodes={},lineStatus){//[{x1,y1},{x2,y2}] //inBranchAndNoNext : 为true时 取当前节点的流转状态
        const { workflowNewDesignStore , isFlowModel = '0'} = this.props;
        const { svgPathLine , wfFreeDatas , circulationParams, forecastNodeIds} = workflowNewDesignStore;
        const { nodeEntity = {} , groupStatus='0', nodeChartEntity = {}} = currNodes;
        const {  nodetype = '' ,nodename=''} = nodeEntity;

        // inBranchAndNoNext ? nodeIsPassed = (groupStatus=='2'?true:false) : '';
        // if(preNode && preNode.groupStatus == 3){ //特殊状态 groupStatus == 3;
        //     nodeIsPassed = false;
        // }

        //console.log(nodename,"----currNodes",mobx.toJS(currNodes),"preNode",preNode.id,mobx.toJS(preNode));
        let nodeIsPassed = lineStatus == 1;

        let strokeColor = this.getStrockColor(nodeEntity.id, lineStatus);
        /**
        //inBranchAndNoNext : 为true时 取当前节点的流转状态
        (//groupStatus : 0 : 未处理 , 1：当前节点 , 2 ： 已处理 
        ----此处需要当此节点已处理后才改变后续连接线颜色)
        */
        points = mobx.toJS(points);

        let svgPath = [];
        let pathProps = {
            fill:'none',
            stroke:strokeColor,
            strokeWidth:'1',
            strokeMiterlimit:10,
            upLevel : nodeIsPassed
        }
        let supHoverParams = {
            strokeWidth:10,
            stroke : 'transparent',
            fill : 'none'
        }
        if(points.length == 2){
            let point_1 = cloneDeep(points[0]) || {};
            let point_2 = cloneDeep(points[1]) || {};
            if(point_1.x == point_2.x && point_1.y == point_2.y){
                return svgPath;
            }
            let pathParams = '';
            if(point_1.x == point_2.x){//在同一竖直线上
                pathParams = `M${point_1.x-0.5} ${point_1.y-0.5} L${point_2.x-0.5} ${point_2.y-0.5}`;
            }else{
                let point_sups = [];
                if(point_1.virtual || point_2.virtual){
                    if(point_1.virtual && point_2.virtual){
                        if(point_1.isBranch){
                            point_sups.push({x:point_2.x , y:point_1.y});
                        }else{
                            point_sups.push({x:point_1.x , y:point_2.y});
                        }
                    }else{
                        if(point_1.virtual){
                            point_sups.push({x:point_2.x , y:point_1.y});
                        }else{
                            point_sups.push({x:point_1.x , y:point_2.y});
                        }
                    }
                    let supPtsParams = '';
                    point_sups.map(pt=>{
                        supPtsParams += `L${pt.x-0.5} ${pt.y-0.5} `;
                    });
                    pathParams = `M${point_1.x-0.5} ${point_1.y-0.5} ${supPtsParams}L${point_2.x-0.5} ${point_2.y-0.5}`;
                }
            }
            svgPath.push(
                <path d={pathParams} {...pathProps}>
                    <title>{nodename}</title>
                </path>
            );
            /**悬浮提示辅助线条 */
            svgPath.push(
                <path d={pathParams} {...supHoverParams}>
                    <title>{nodename}</title>
                </path>
            );

            if(currNodes.nodeElement && !point_2.virtual && !(isFlowModel == '1' && nodetype == '3')){
                svgPath.push(this.renderSvgArrow(point_2,'fill',nodeIsPassed,true,nodetype, nodeEntity.id));
            }
        }
        return svgPath;
    }
    renderSvgArrow(point={} , arrowType = 'notfill' , nodeIsPassed , vertical = false,nodetype, nodeid){
        const { workflowNewDesignStore } = this.props;
        const { circulationParams} = workflowNewDesignStore;
        let strokeColor = this.getStrockColor(nodeid, nodeIsPassed ? 1 : 0, '#8c8c8c');
        let arrowWidth = 7;
        let arrowHight = 8;
        let arrowGap = 50;
        let arrowParams = '';
        let pathParams = {
            // stroke:nodeIsPassed ? circulationParams.passedLinkColor : circulationParams.noPassedLinkColor,
            stroke:strokeColor,
            fill : strokeColor,
            strokeWidth:'1',
        };
        let OffsetTrans_x = 0 , OffsetTrans_y = 0;
        if(nodetype == '0' || nodetype == '3'){//创建 || 归档
            // pathParams['transform'] = `translate(-0.5px, 0.5px)`;
            OffsetTrans_x = -0.5;
            OffsetTrans_y = 0.5;
        }else if(nodetype == '2' || nodetype == '4'){//提交 || 审阅
            // pathParams['transform'] = `translate(-0.5px, 13.5px)`;
            OffsetTrans_x = -0.5;
            OffsetTrans_y = 13.5;
        }else{//审批
            // pathParams['transform'] = `translate(-0.5px,-1.5px)`;
            OffsetTrans_x = -0.5;
            OffsetTrans_y = -1.5;
        }
        if(arrowType != 'fill'){//配置箭头样式， fill 或者 stroke
            pathParams.fill = 'none';
        }
        let X = point.x || '';
        let Y = point.y || '';
        if(vertical){
            arrowParams = `M${point.x - arrowHight/2 + OffsetTrans_x} ${point.y - arrowGap - arrowWidth+OffsetTrans_y} L${point.x+OffsetTrans_x} ${point.y 
            - arrowGap+OffsetTrans_y} L${point.x + arrowHight/2+OffsetTrans_x} ${point.y - arrowGap - arrowWidth+OffsetTrans_y}`;
        }else{
            arrowParams = `M${X - arrowWidth} ${(Y) - arrowHight/2} L${X} ${Y } L${X - arrowWidth} ${(Y) + arrowHight/2}`;
        }
        return (
            <path d={arrowParams} {...pathParams} style={{"transform":pathParams['transform'],"-ms-transform":pathParams['transform']}}>
            </path>
        )
    }
    drawLastSvgLine(centerY = 400,currentNodeIsPassed,lastPoints={},nodetype,element,ptIndex,outLineStatus){
        const { workflowNewDesignStore , isFlowModel ,isFree} = this.props;// endPosition = {x:30,y:0} ,
        const { wfFreeDatasPoints , wfFreeDatas , circulationParams , currentPostParams,
        allValidNodesPostions,allValidNodesNodeLinks,currentSignSetNode,validWorkFlowDatas,everyFreeNodeOffsetY,circulationOrginNode,forecastNodeIds} = workflowNewDesignStore;
        const { nodeName = '' , nodeType = '0' , flowType='1'} = currentSignSetNode;
        const {  allValidNodes = [], currentStartNode , currentEndNodes} = validWorkFlowDatas;

        /** 多个终点处理  获取所有后续出口节点*/
        const {freeStartNodeid,freeEndNodeid} = element;
        let freeNodeEndArr = [];
        if(freeStartNodeid == freeEndNodeid) {
            const {allOrginNodes = []} = toJS(circulationOrginNode);
            let linkname  = '';
            for (let index = 0; index  < allOrginNodes.length ;index++) {
                let item = allOrginNodes[index];
                if(item.nodeId  == freeStartNodeid) {
                    linkname = item.value;
                    break
                }
            }
            freeNodeEndArr.push({
                id:'',
                descnode : freeStartNodeid,
                linkname : '',
                linkinfo : linkname,
                ispass : currentNodeIsPassed ? '1' : '0',
            })
        } else {
            freeNodeEndArr =  allValidNodesNodeLinks[freeStartNodeid] || []
        }

        /********** */
        if(isFlowModel == '1'){
            return [];
        }
        let maxX = 0 , maxY = 0;
        let lastArr = [];
        let newPtsObj = cloneDeep(wfFreeDatasPoints[ptIndex]);
        let curFreeNodeOffsetY = everyFreeNodeOffsetY[freeStartNodeid] || 0;
        
        for(let key in newPtsObj){
            let idsArr = key.split('_') , newidArr=[] , _ids = '';
            idsArr.map((v,i)=>{
                if(i != idsArr.length -1){
                    newidArr.push(v);
                }
            });
            _ids = newidArr.join('_');
            if(isExistThisElement(_ids,element)){//删除后  不存在的元素 或分支 的点依然存在在数据当中 需要过滤
                maxX = maxX > newPtsObj[key].x ? maxX : newPtsObj[key].x;
                maxY = maxY > newPtsObj[key].y ? maxY : newPtsObj[key].y;
            }
        }

        let branchEndLinks = sortBy(toJS(freeNodeEndArr), ['ispass']);
        cloneDeep(branchEndLinks).map((v,i)=>{
            const linktitle = convertSpecialChar(v.linkinfo);
            let endPosition = cloneDeep(allValidNodesPostions[v.descnode]);
            let ispassed = currentNodeIsPassed && v['ispass'] == '1';

            let pathProps = {
                fill:'none',
                // stroke:ispassed ? circulationParams.passedLinkColor : circulationParams.noPassedLinkColor,
                stroke:this.getStrockColor(freeEndNodeid, ispassed ? 1 : 0, circulationParams.noPassedLinkColor, v.descnode),
                strokeWidth:'1',
                strokeMiterlimit:10,
            }

            if(isFree != '1' && freeStartNodeid == v.descnode){
                endPosition = {...endPosition,x:endPosition.x+6}
            }
            let points = [
                {x:lastPoints.x,y:lastPoints.y},
                {x:lastPoints.x,y:lastPoints.y + (nodetype=='1'?80:60)},
                {x:maxX + 93 ,y:lastPoints.y + (nodetype=='1'?80:60)},
                {x:maxX + 93 ,y:curFreeNodeOffsetY},
                // {x:maxX + 93 ,y:0},
            ];
            let pathParams = ``;

            points.map((c,k)=>{
                if(k == 0){
                    pathParams += ('M'+(c.x-0.5)+' '+(c.y-0.5)+' ');
                }else{
                    pathParams += ('L'+(c.x-0.5)+' '+(c.y-0.5)+' ');
                }
            });
            lastArr.push(
                <path d={pathParams} {...pathProps}>
                    <title>{linktitle}</title>
                </path>
            );
            /**绘制最后一条线上方的 横向的线条  */
            let adjustEndPosValue = (endPosition.x > maxX + 93 || isFree == '1') ? 1 : 0;
            lastArr.push(
                <path d={`M${maxX + 93} ${curFreeNodeOffsetY + 0.5} L${endPosition.x + adjustEndPosValue} ${curFreeNodeOffsetY + 0.5}`} {...pathProps} 
                    stroke = {this.getStrockColor(freeEndNodeid, ispassed ? 1:0, '#666666', v.descnode)}
                    >
                    <title>{linktitle}</title>
                </path>
            );
            /** 悬浮辅助线条 不然1px svg元素不好选中显示title信息*/
            let supHoverParams = {
                strokeWidth:10,
                stroke : 'transparent',
                fill : 'none'
            }
            lastArr.push(
                <path d={pathParams} {...supHoverParams}>
                    <title>{linktitle}</title>
                </path>
            );
            lastArr.push(
                <path d={`M${maxX + 93} ${curFreeNodeOffsetY + 0.5} L${endPosition.x} ${curFreeNodeOffsetY + 0.5}`} {...supHoverParams}
                    >
                    <title>{linktitle}</title>
                </path>
            );
            /***************/
        });
        
        return lastArr;
    }
    /**
    加签时，渲染一个可点击区域覆盖在之前的节点之上
     */
    renderSignHideBtn(){
        let { workflowNewDesignStore , cellMaxHeight = 0 , isFree='',isFlowModel,isReadOnlyModel,isMobile='0'} = this.props;
        const { circulationOrginNode , currentSignSetNode , rightDetailType , freeWfTrunkNodes,getFreeNodeSetting,currentFlowingGroup,
        curFloatSignNodeId,setPopOperatorsPanemParams,setCurrentElement_mobile,validWorkFlowDatas,currentValidStartNodeId} = workflowNewDesignStore;
        const {  allValidNodes = []} = validWorkFlowDatas;
        isReadOnlyModel = isReadOnlyModel == 'true' ? true : false;
        let signBtns = [];
        allValidNodes.map(v=>{
            const { geometry = {} , nodeId = '' , style = ''} = v;
            const { x = 0, y = 0 , width = 0 , height = 0} = geometry;
            //获取原始流程图节点样式
            let orginNodeStyle = style.split(';').filter(v=>v.indexOf('strokeColor')>-1)[0].split('=')[1];
            const curStyle={
                width : width + 'px',
                height : height + 'px',
                left : (x + 1 )+ 'px',
                top : -(cellMaxHeight - y -1) + 'px',
            };
            const floatBtnStyle = {
                left : width / 2 - 11 + 'px' ,
                bottom:'-10px'
            }
            signBtns.push(<div 
                className='sign-hide-btn-area' 
                style = {curStyle}
                onMouseEnter = {()=>{workflowNewDesignStore.curFloatSignNodeId = nodeId;}}
                onMouseLeave = {()=>{workflowNewDesignStore.curFloatSignNodeId = '';}}
                onClick={(event)=>{
                    const { startGroup = {}, endGroup = {} } = freeWfTrunkNodes;
                    const {nodeEntity={}} = startGroup;
                    let nodeinfo;

                    if(nodeEntity.id == nodeId){
                        nodeinfo = startGroup;
                    }else{
                        nodeinfo = endGroup;
                    }
                    if(isEmpty(nodeinfo)){
                        nodeinfo = {
                            nodename:v.value,
                            nodetype : v.nodeType
                        }
                    }
                    if(isMobile == '0'){//pc
                        if(isReadOnlyModel){
                            const { pageX , pageY } = event;
                            setPopOperatorsPanemParams({position:{left:pageX,top:pageY},visible:true,nodeinfo});
                        }else{
                            if(isFree == '1'){
                                workflowNewDesignStore.rightDetailType = 'node';
                                getFreeNodeSetting(nodeinfo);
                            }else{
                                if(currentValidStartNodeId != nodeId){
                                    return;
                                }
                                workflowNewDesignStore.rightDetailType = 'signSet';
                                workflowNewDesignStore.currentChoosedBranchId = '';
                                workflowNewDesignStore.currentChoosedItemId = '';
                                const obj = {
                                    nodeName : v.value,
                                    nodeType : v.nodeType
                                };
                                workflowNewDesignStore.currentSignSetNode = {...currentSignSetNode,...obj};
                            }
                        }
                    }else{
                        /**
                            移动端编辑模式下点击 老流程图节点
                            自由流程：只有创建节点可以点击，点击后下方出现“添加串行节点图标”
                            加签：
                        */
                        nodeinfo['isAddSign'] = isFree == '1' ? false : true;
                        setCurrentElement_mobile(nodeinfo,false,currentValidStartNodeId+'');
                    }
                }}>
                {(isFlowModel!='1' &&!isReadOnlyModel && (curFloatSignNodeId==nodeId)) && 
                    (isMobile=='0' ||(isMobile=='1' && isFree!='1'))&&this.renderFloatAddButton(floatBtnStyle)}
            </div>);
        });
        
        return signBtns;
    }
    renderFloatAddButton(params){//渲染浮动在流程图节点上的添加按钮
        const { topParams = {} , workflowNewDesignStore} = this.props;
        const { currentFreeWfEditState , wfFreeDatas , beSerialNodes,curFloatSignNodeId,circulationOrginNode,allowAddNewBranch,
        currentValidStartNodeId,validWorkFlowDatas} = workflowNewDesignStore;
        const { currentStartNode } = validWorkFlowDatas;
        const { startOrginNodeId } = circulationOrginNode;
        let btns = [];
        if(curFloatSignNodeId==currentValidStartNodeId && allowAddNewBranch){
            btns.push(
                <Button ecId={`${this && this.props && this.props.ecId || ''}_Button@slk6px@${currentValidStartNodeId}`} type='ghost' onClick={()=>beSerialNodes('root',currentValidStartNodeId+'')}>
                    <span className="icon-coms-Enlarge" title={getLabel(506900,'添加串行节点')}></span>
                </Button>
            );
        }
        return (
            <div className='float-sign-btn' style={params}>
                {btns}
            </div>
        );
    }

    getStrockColor(nodeid, inLineStatus, noPassedLinkColor, descnode) {
        const { workflowNewDesignStore } = this.props;
        const { forecastNodeIds, circulationParams } = workflowNewDesignStore;

        //是否为预测出来的节点
        let isForecastNode = false;
        if(descnode != undefined && descnode != '') {//有传入出口到达节点，用此节点判断。简易模式下传入的endNodes不准确
            isForecastNode = forecastNodeIds && forecastNodeIds != '' && (","+forecastNodeIds+",").indexOf(","+descnode+",") > -1;
        } else {
            isForecastNode = forecastNodeIds && forecastNodeIds != '' && (","+forecastNodeIds+",").indexOf(","+nodeid+",") > -1;
        }
        if(nodeid == undefined && forecastNodeIds && forecastNodeIds != '') {
            isForecastNode = true;
        }

        let strokeColor = '';
            if(inLineStatus == 1 ) {
                strokeColor = circulationParams.passedLinkColor;
            } else if(isForecastNode){
                strokeColor = circulationParams.forecastLinkColor;
            } else {
                strokeColor = noPassedLinkColor ? noPassedLinkColor : circulationParams.noPassedLinkColor;
            }
        return strokeColor
    }
}


export default WeaTools.tryCatch(React, 
    props => <WeaErrorPage ecId={`${this && this.props && this.props.ecId || ''}_WeaErrorPage@3tvdmz`} msg={ props.error ? props.error : getLabel(383324,' 对不起，该页面异常，请联系管理员 ')+'！'} />,
    {error: ""}
)(WorkflowFree);